
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;

using System.Net;
using Swaf;
using Swaf.BizObj;
using Swaf.BizRule;
using Swaf.Container;
using Swaf.Security;

namespace Articles
{
    public class YoutubeBizRules : Syrinx.BaseBizRules
    {
		static string s_embedBody = "<object width=\"425\" height=\"355\"><param name=\"movie\" value=\"http://www.youtube.com/v/{0}&rel=1\"></param><param name=\"wmode\" value=\"transparent\"></param><embed src=\"http://www.youtube.com/v/{0}&rel=1\" type=\"application/x-shockwave-flash\" wmode=\"transparent\" width=\"425\" height=\"355\"></embed></object>{1}";
        static string s_YOUTUBEAPIURL = "http://www.youtube.com/api2_rest";
        static string s_devId = "4wwm21u3kZo";

        public XmlDocument getYoutubeResponseDoc(IApplication app, IRuleContext context, FlexiMap m)
        {
            string userId; 
            int pageNumber, perPage;
            userId = (string)m["userId"];
            pageNumber = (int)m["page"];
            perPage = (int)m["max"];
            string baseArticleUniqueName =m["baseArticleUniqueName"].ToString();

            IBizObjList articles = (IBizObjList)context.get("articles");
            string catalogName = (string)context.get("catalogName");

            if (perPage > 100)
                perPage = 100;

            XmlDocument doc = null;
            string requestUri =
                String.Format("{0}?method={1}&dev_id={2}&user={3}&page={4}&per_page={5}", s_YOUTUBEAPIURL, "youtube.videos.list_by_user", s_devId, userId, pageNumber, perPage);

            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);

                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (System.IO.Stream responseStream = response.GetResponseStream())
                    {
                        doc = new XmlDocument();
                        doc.Load(responseStream);
                    }
                }

                XmlNode node = doc.SelectSingleNode("ut_response"); 
                if (node.Attributes["status"].Value == "ok")
                {
                    int total;
                    int.TryParse(node.SelectSingleNode("//total").InnerText, out total);
                    if (total > 0)
                    {
                        IBizObj parentArticle = null;

                        if (articles == null || articles.numElements == 0)
                        {
                            if (articles == null)
                                articles = app.bizObjMgr.createList("Article");
                            parentArticle = articles.insertNew();
                            parentArticle.put("id", new Swaf.BGuid.Guid());
                            parentArticle.put("uniqueTitle", baseArticleUniqueName);
                            parentArticle.put("baseTitle", "User You Tube Videos");

                            app.ruleMgr.execute("updateArticle", parentArticle);
                        }

                        if (articles == null)
                            throw new Articles.ArticlesException("Cant create articles for you tube videos");

                        parentArticle = articles[0];
                        XmlNodeList lst = node.SelectNodes("//video");
                        IRuleGroup ruleGroup=null;
                        for (int i = 0; i < lst.Count; i++)
                        {
                            m["node"] = lst[i];
                            FlexiMap param = new FlexiMap(m, false); // make sure we have new param always
                            context.RuleGroup.execute(context, "addYoutubeArticle", null, null, param);
                        }
                    }
                }
                return doc;
            }
            catch (Exception e)
            {
                throw new ArticlesException("Error executing getYoutubeResposeDoc", e);
            }
        }

        /// <summary>
        /// this bizrule should only be used enternally specifically by getYoutubeResponseDoc
        /// </summary>
        /// <param name="app"></param>
        /// <param name="context"></param>
        /// <param name="m"></param>
        public void addYoutubeArticle(IApplication app, IRuleContext context, FlexiMap m)
        {
            IBizObjList articles = (IBizObjList)context.get("articles");
            string catalogName = context.get("catalogName").ToString();
            string baseArticleUniqueName = m["baseArticleUniqueName"].ToString();

            XmlNode node = (XmlNode)m["node"];
            IBizObj parentArticle = ((IBizObjList)context.get("articles"))[0];

			string utubId = node.SelectSingleNode("id").InnerText.ToString();
			string id = baseArticleUniqueName + utubId;
            IBizObj article = articles.search("uniqueTitle", id, false);
            if (article == null)
            {
                //this is hack to force saving of utube images to utube dir 
				// in imagecache directory
				string videoImageName = string.Format("uTube{0}{1}.jpg",Path.DirectorySeparatorChar ,id);
                article = app.bizObjMgr.create("Article");
                article.put("id", new Swaf.BGuid.Guid());
                article.put("parentId", parentArticle.get("id"));
                article.put("keyword", node.SelectSingleNode("tags").InnerText);
				string desc = node.SelectSingleNode("description").InnerText;
				string summary = desc.Length > 250?desc.Substring(0,250):desc;
                article.put("baseSummary", summary);
                article.put("baseTitle", node.SelectSingleNode("title").InnerText);
                article.put("baseBody", string.Format(s_embedBody, utubId,desc));
				article.put("uniqueTitle", id);
				article.put("treeName", "Articles");

                IBizObj videoImage = app.bizObjMgr.create("Image");
                videoImage.put("name", videoImageName);
                Binary bin = new Binary(); //(Binary)videoImage.get("data");
                Stream imageData = bin.DataStream;

                HttpWebRequest imageRequest = (HttpWebRequest)WebRequest.Create(node.SelectSingleNode("thumbnail_url").InnerText);
                using (HttpWebResponse response = (HttpWebResponse)imageRequest.GetResponse())
                {
                    using (System.IO.Stream responseStream = response.GetResponseStream())
                    {
                        int b;
                        while ((b = responseStream.ReadByte()) != -1)
                            imageData.WriteByte((byte)b);
                        imageData.Position = 0;
                    }
                }
                videoImage.put("data", bin);
				article.put("dateCreated", DateTime.Now.ToUniversalTime());

                article.put("primaryPicture.name", videoImageName);
                app.ruleMgr.execute("addImage", catalogName, videoImage);
                app.ruleMgr.execute("updateArticle", article);
            }
        }

        /// <summary>
        /// Calls the youtube.videos.list_by_user REST method
        /// For more details see http://www.youtube.com/dev_api_ref?m=youtube.videos.list_by_user
        /// </summary>
        /// <param name="devId">The dev id.</param>
        /// <param name="userId">The user id.</param>
        /// <returns></returns>
        public void uploadYoutubeArticles(IApplication app, IRuleContext context, IBizObj info)
        {
            try
			{
				XmlDocument doc = null;
				string catalogName = ActiveCompany.get("settings.defaultMediaCatalogName").ToString();
                context.put("parentId", info.get("baseArticleUniqueName"));
                context.put("listDetailLevel", DetailLevel.idAndTitle);
                context.put("includeSelf", true);
                context.put("entireTree", false);
                IBizObjList articles = app.ruleMgr.execute("getArticles", context, (IBizObj)null).CallResults as IBizObjList;
                context.put("articles", articles);
                context.put("catalogName", catalogName);
                int max = 10;
                FlexiMap m = new FlexiMap();
				m["userId"] = info.get("youTubeAccountName");
                m["page"] = 1;
                m["max"] = max;
                m["baseArticleUniqueName"] = info.get("baseArticleUniqueName");

                IRuleGroup ruleGroup = app.ruleMgr.execute(context, "getYoutubeResponseDoc", null, null, m);
                ruleGroup.waitForCompletion(true);
                doc = ruleGroup.CallResults as XmlDocument;

				XmlNode node = doc.SelectSingleNode("ut_response");
                if (node.Attributes["status"].Value == "ok")
                {
                    int total;
                    int.TryParse(node.SelectSingleNode("//total").InnerText, out total);
                    int maxLoop = 0;
                    if (total > max)
                        maxLoop = (int)Math.Ceiling((decimal)total / (decimal)max);
                    for(int i =2; i <= maxLoop; i++)
                    {
                        m["page"] = i;
                        FlexiMap param = new FlexiMap(m,false);//make sure we have new param always
                        ruleGroup.execute(context, "getYoutubeResponseDoc", null, null, param);
                    }
                }
				else
				{
					throw new Articles.ArticlesException(node.SelectSingleNode("description").Value.ToString());
				}
                ruleGroup.waitForCompletion(true);
			}
			catch (Articles.ArticlesException)
			{
				throw;
			}
			catch (Exception e)
			{
				throw new ArticlesException("Error Executing UploadYoutubeArticles", e);
			}
        }

        /*
        //http://www.youtube.com/api2_rest?method=youtube.videos.list_by_user&dev_id=4wwm21u3kZo&user=mattsyrinxxxx&page=1&per_page=100
        public XmlDocument getYoutubeResponse(IApplication app, IRuleContext context, string userId,int page, int max)
        {

        }*/

        #region youtube article configuration
        public void updateYoutubeArticleConfiguration(IApplication app, IRuleContext context,IBizObj youtubeConfig)
        {
            try
            {
                app.ruleMgr.execute("deleteYoutubeArticleConfiguration", youtubeConfig);
                app.appData.put("Data.ArticlesAdmin.InsertYoutubeConfig", youtubeConfig);
            }
            catch (Exception e)
            {
                throw new ArticlesException("Error executing updateYoutubeArticleConfiguration", e);
            }
        }

        public void deleteYoutubeArticleConfiguration(IApplication app, IRuleContext context, IBizObj youtubeConfig)
        {
            try
            {
                FlexiMap m = new FlexiMap();
                app.appData.get("Data.ArticlesAdmin.DeleteYoutubeConfig", m);
            }
            catch (Exception e)
            {
                throw new ArticlesException("Error executing deleteYoutubeArticleConfiguration", e);
            }
        }

        public IBizObj getYoutubeArticleConfiguration(IApplication app, IRuleContext context,Swaf.BGuid.Guid id)
        {
            try
            {
                FlexiMap m = new FlexiMap();
                m["articleId"] = id;
                IBizObjList lst = (IBizObjList)app.appData.get("Data.ArticlesAdmin.GetYoutubeConfig", m);
                return lst.Count > 1 ? lst[0] : lst.insertNew();
            }
            catch (Exception e)
            {
                throw new ArticlesException("Error executing deleteYoutubeArticleConfiguration", e);
            }
        }
        #endregion
    }
}
